Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logic Toolbox #308

Open
wants to merge 5 commits into
base: upsilon-dev
Choose a base branch
from
Open

Conversation

joecrop
Copy link

@joecrop joecrop commented Dec 27, 2022

Binary Logic Toolbox

Numworks is about to release some basic binary functions in Epsilon. I tried them out, and they are honestly pretty useless, with inputs of just 'True' and 'False' and just AND/OR/NOT functions. Here's my take on a toolbox with much more powerful logic functions to be used on both unsigned and signed integers. I have also extended the '...' (Additional Results) display to show the 2's complement binary/hex of negative numbers.

logic_toolbox

Additional Results

Negative integers can now be displayed in binary/hex. Simply navigate to the ellipsis ('...') on the right of a negative integer result to see a 2's complement representation of the number:

negative_binary_results

Functions Implemented

Basic Logic Operations

AND

// x = a & b
and(a, b); // and of 2 integers

// Examples
and(0b11,0b01) = 1;
and(0b100110,0b1011) = 2;

OR

// x = a | b
or(a, b); // or of 2 integers

// Examples
or(0b11,0b01) = 3 = 0b11;
or(0b100110,0b1011) = 47 = 0b101111;

XOR - Exclusive OR

// x = a ^ b
xor(a, b); // xor of 2 integers

// Examples
xor(0b11,0b01) = 1;
xor(0b100110,0b1011) = 45 = 0b101101;

NOT

// x = ~a
not(a); // logical inversion of 32-bit unsigend integer

// Examples
not(0b11) = 4294967292 = 0xFFFFFFFC;
not(0xFFFF0000) = 65535 = 0xFFFF;

Bit Shifts

Shift Logical Left

// x = a << s
sll(a, s) // shift 'a' left by 's' bit positions

// Examples
sll(0b11,2) = 12 = 0b1100;

Shift Logical Right

// x = a >> s
srl(a, s) // shift 'a' right by 's' bit positions

// Examples
srl(0b11,2) = 0;
srl(0b1100,1) = 6 = 0b110;

Arithmetic Shift Right

// x = a >>> s
sra(a, s) // shift 'a' right by 's' bit positions, perserving the MSB sign bit, where 'a' is presumed to a 32 bits

// Examples
sra(0b11,2) = 0;
sra(0b1100,1) = 6 = 0b110;
sra(0xFFFF0000,8) = 4294967040 = 0xFFFFFF00;

Rotate Left

// x = (a << r) | (a & 1)
rol(a, r) // rotate 'a' by 'r' bit positions, the MSB is warpped around to the LSB, where 'a' is presumed to a 32 bits

// Examples
rol(0b101,1) = 10 = 0b1010;
rol(0xFFFF0000,4) = 4293918735 = 0xFFF000F;

Rotate Right

// x = (a >> r) | ((a & 1) << 32)
ror(a, r) // rotate 'a' by 'r' bit positions, the LSB is warpped around to the MSB, where 'a' is presumed to a 32 bits

// Examples
ror(0b1010,1) = 5 = 0b101;
ror(0b101,1) = 1073741825 = 0x40000001;
ror(0xFFFF0000,4) = 268431360 = 0x0FFFF000;

Setting And Clearing Bits

Get Bit

// (a >> n) & 1
bit(a, n) // return the n-th bit of 'a'

// Examples
bit(0b1010,1) = 0;
bit(0b1010,2) = 1;

Set Bit

// x = a | (1 << n)
bset(a, n) // set the n-th bit of 'a'

// Examples
bset(0b1010,1) = 11 = 0b1011;
bset(0b1010,2) = 10 = 0b1010;

Clear Bit

// x = a & ~(1 << n)
bclr(a, n) // clear the n-th bit of 'a'

// Examples
bclr(0b1010,1) = 10 = 0b1010;
bclr(0b1010,2) = 8 = 0b1000;

Flip Bit

// x = a ^ (1 << n)
bflp(a, n) // flip the n-th bit of 'a'

// Examples
bflp(0b1010,1) = 11 = 0b1011;
bflp(0b1010,2) = 8 = 0b1000;

Clear 'a' With 'b'

// x = (a & ~b)
bic(a, b) // clear 'a' with 'b'

// Examples
bic(0b1010,1) = 10 = 0b1010;
bic(0b1010,0b10) = 8 = 0b1000;
bic(0b1010,0b1010) = 0;

Logic Operations (With Explicit Number of Bits)

Some logic operations (like NOT) end up generating large 32-bit numbers as the default precision is 32 bits. This adds frustration when 32 bits of precision is undesired. So some of the functions have overridden methods that have an extra argument that allows the user to control the number of output bits.

not(a,n);
sra(a,s,n);
rol(a,r,n);
ror(a,r,n);
bic(a,b,n);

// Examples
not(0b11) = 4294967292 = 0xFFFFFFFC;
not(0b11,8) = 252 = 0b11111100;
not(0b00,2) = 3 = 0b11;
not(0b10,1) = 1 = 0b1;
not(0b0,1) = 1 = 0b1;
not(0b1,1) = 0 = 0b0;

2'S Compliment Conversions/Helpers

2's Compliment Equivalent

// Converts an unsigned binary number to it's two-compliment equivalent Integer.
// Simply useful to decode binary numbers that are negative

// Examples:
// If argument 1 is positive, the output will be converted to two-s comp (i.e. look at sign bit in MSB)
tc(0xFF, 8) = -1;
tc(0x0F, 8) = 15;

// if argument 1 is negative, it is always converted to unsigned
tc(-1, 8) = 255;

Ceiling Log2

// Returns the numver of bits required to represent a number in binary.
clog2(255) = 8;
clog2(3) = 2;

//NOTE: this is not the same as ceil(log(x,2)), as negative inputs to this function will instead be treated as 2's compliment numbers it report the number of bits needed to represent a signed 2's compliment number.
clog2(-3) = 2; // -3 in binary 2's compliment is 0b100
// If you want to konw the number of bits of an unsigend number in 2'c compliment number, just add 1 to the result for a sign bit.

Other Information

@github-actions
Copy link

.text .rodata .bss .data Total (RAM) Total (ROM)
Base 821684 bytes 478173 bytes 226384 bytes 1816 bytes 228200 bytes 1301673 bytes
Head 834324 bytes 486889 bytes 226376 bytes 1816 bytes 228192 bytes 1323029 bytes
+12640 bytes +8716 bytes -8 bytes +0 bytes -8 bytes +21356 bytes
+1.5 % +1.8 % -0.0 % +0.0 % -0.0 % +1.6 %

apps/toolbox.fr.i18n Outdated Show resolved Hide resolved
LogicalRotateLeft = "Rotation gauche de a par r bits"
LogicalRotateRight= "Rotation droite de a par r bits"
TwosComplementToBits = "Equivalent en complément à deux"
CeilingLog2 = "Nombre de bits nécessaires pour stocker a"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The text is too long (maybe shortening Nombre to nb would help)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Nombre de bits nécessaires pour stocker a' is now 'Nb de bits nécessaires pour stocker a'

LogicalBitClear = "Effacer le bit numéro b dans a"
LogicalBitFlip = "Inverser le bit numéro b dans a"
LogicalBitGet = "Obtenir le bit numéro b dans a"
LogicalBitSet = "Allumer le bit numéro b dans a"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allumer is not the right word here. I'd use something like mettre/définir

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed 'Allumer' to 'Mettre'

@github-actions
Copy link

.text .rodata .bss .data Total (RAM) Total (ROM)
Base 821684 bytes 478173 bytes 226384 bytes 1816 bytes 228200 bytes 1301673 bytes
Head 834324 bytes 486881 bytes 226376 bytes 1816 bytes 228192 bytes 1323021 bytes
+12640 bytes +8708 bytes -8 bytes +0 bytes -8 bytes +21348 bytes
+1.5 % +1.8 % -0.0 % +0.0 % -0.0 % +1.6 %

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants